docs(changeset): correct four statements in the pending enableOnInstall one-authority note - #19747
Conversation
…ll one-authority note The fragment is pending and unreleased, so `changeset version` publishes its prose verbatim into `packages/spec/CHANGELOG.md`. Four of its statements about the published surface no longer hold at `origin/main`: - the install door's rule, spelled `enableOnInstall ?? true` — the door has implemented three states (`=== true` / `=== false` / absent) since the install contract was re-ruled; `?? true` is the reading the tree has explicitly retired; - a verbatim quotation of the authority's published description that the description no longer carries; - "same default" on the kernel copy — both declarations are `z.boolean().optional()` and neither carries a default; - "this layer does not read it: the implementation reads `manifest` and `settings` only" — the protocol primitive reads `request.enableOnInstall` and branches `=== true` / `=== false` on it. Corrected in place rather than by restoration or by an erratum in a later entry, and worded to name the mechanism rather than a count so the sentences do not fall out of date again before publication. Every other byte of the fragment, including the statements that are dated by design, is unchanged. Claude-Session: https://claude.ai/code/session_013RDBh5DqXd2xnLwvHLgLFr Co-authored-by: Claude <noreply@anthropic.com>
Seat note — the scope question is ANSWERED: all four corrections stay. Plus two measurements that correct the record, one of them this seat's own error.Written by the 1. ⭐ The two extra corrections are ACCEPTED. ⛔ Do not revert them.The round offered: 「⛔ If the seat prefers the card's exact two, (3) and (4) are a one-commit revert — say so and they come out.」 The seat says keep them, and the reasoning is measured rather than deferential:
The seat re-took (3)'s load-bearing reading rather than adopting it
⇒ the install door was already three-state when the fragment was written. (3) is false-when-written, ⛔ not overtaken. Confirmed independently. Firing / dark controls on the decisive instrument: 2.
|
| commit | file carrying the string |
|---|---|
596090efbe |
packages/spec/src/api/package-api.zod.ts (1), packages/spec/src/kernel/package-registry.zod.ts (1) |
482d584121 |
packages/objectql/src/protocol-install-package-enable-on-install.test.ts (2) |
fb59fb5e37 |
— (the string's count changed without landing in a file that still carries it) |
⇒ the string did live in two packages/spec source files — inside the published .describe() text, which is source bytes rather than executable logic. ⭐ That does not weaken (3); if anything it strengthens it, because the false rule was published in the schema descriptions too and has since been rewritten there. The load-bearing claim — that the door's behaviour was never ?? true — stands on its own instrument above.
3. ⚠️ This seat's own error, owned rather than quietly fixed
The dispatching claim 5783373652 and the card both describe the fragment as "@objectstack/spec": patch. At source it is minor. Re-measured at origin/main at 2026-09-22T20:30Z:
---
"@objectstack/spec": minor
---
The round caught it and recorded it in its acceptance notes; ⛔ it is not the round's to change and it did not change it, which is right. The seat carried patch from the card without re-measuring it — the same class of failure the claim itself warned the round against two paragraphs earlier. Recorded here because it is not cosmetic: it says the corrected prose publishes on a minor release of @objectstack/spec, ⛔ not a patch.
Also measured and worth naming so it is not a surprise to the carriers reader: line 9 of the fragment carries a pre-existing clause-② declaration reading yes — it belongs to #19130's change (which did move published surface), ⛔ not to this branch, whose own declaration is no and is correct: this diff moves no key, no type, no default and no accept set.
4. ⛔ What is still owed, and by whom
- The at-tier contract review — the seat's to arrange, and it is being arranged now through an isolated at-tier subagent.
⚠️ Its basis is the lane rule (C6, this card isdomain:spec), ⛔ not the clause-② path limb, which does not fire on a.changeset-only diff. - The route-0 countersignature — a HUMAN act, and ⛔ this seat cannot supply it.
pr-automation.ymlroute 0 asks for the confirmation to be 「get it confirmed there in writing」 and states 「the approver merges over it」. The red exists to put the decision in front of a person, so this seat arming auto-merge would route around the one thing the gate is for.⚠️ A PASS on the review does ⛔ NOT discharge this.
5. CI on head fbb8952c3e, read from GitHub per check name at 2026-09-22T20:30Z
25 runs: 19 success or path-filtered skipped, 0 failure, and 6 in_progress — Lint & Repo Gates, the four Type Check jobs, and Check Changeset itself. in_progress is NOT MEASURED, ⛔ never a pass; the review will read them at its own moment. Check Changeset is expected to land RED by route 0 and ⛔ that red is not a blocker.
Generated by Claude Code
|
|
Served-tier: 142/142 Contract-review record — PR #19747 (
|
Seat disposition of the FAIL — the finding is CONFIRMED, and ⛔ its root is NOT on this PR's surfaceWritten by the The four corrections all PASS at source. The FAIL rests on one pre-existing, retained sentence the round declared it had 「re-derived and it stands」 — and it does not. Confirmed by the seat, independently, at both treesLine 19 of the fragment says the authority is built from
⇒ 「both」 is wrong: one of the two is declared there, the other is imported. And it was wrong at the seeding tree as well, so this is false-when-written, ⛔ not overtaken. Dark control: ⭐ But the root is a live error in SHIPPED SOURCE, and that changes what to doThe fragment did not invent the sentence — it copied one.
The identical wording sits at the seeding commit (
⛔ The seat does not widen a fifth time, and the reviewer's own premise is whyThe record's remedy is 「one clause in the same file, and this PR is the only non-colliding carrier」. That premise is true of the copy and ⛔ false of the root: the root is in And twenty minutes ago this seat posted ⇒ What happens instead
⛔ What the countersigner is being asked, stated plainlyThis PR corrects four statements, and the at-tier review finds all four correct at source. It also finds a fifth false sentence — pre-existing, retained, measured above — which this PR does not touch, and the review's verdict is FAIL for that reason alone. Three ways forward, and ⛔ this seat is not choosing for you:
⭐ This seat's recommendation is B, and the recommendation is ⛔ not a substitute for your decision. The PR has not left draft; ⏱️ Generated by Claude Code |
Maintainer instruction —
|
Confirmation of record (ruling D ② B) — replaces the label route
⇒ Ruling D stands. The confirmation is this chat sentence, carried here. Generated by Claude Code |
Fixes #19735
What this changes
Four statements in
.changeset/18605-enable-on-install-one-authority.md— a pending, unreleased fragment whose prosechangeset versionpublishes verbatim intopackages/spec/CHANGELOG.md. One file, three lines,+3 / -3. No other fragment and no other file in the tree is touched, and the fragment's own"@objectstack/spec": minorheader is untouched.The card named two of the four. The other two were found by the re-derivation the card and the claim both demanded, and they are the same defect in the same paragraph — a statement about the published surface that the published surface no longer supports. Each of the four is quoted old and new below, and the two extras are kept in their own subsection so that what is being confirmed here is unambiguous.
DELIBERATE CORRECTION — this is the written confirmation
pr-automation.ymlroute 0 requires, andCheck Changesetis RED on purposeThis PR adds no changeset of its own; it changes a pending changeset it did not add. Route 0's discriminator, run against this PR's merge base:
Every row is
M, none isA⇒ route 0. The class is DELIBERATE CORRECTION, not COLLISION: this PR did not draw that filename, nothing of its own was overwritten, and the base copy must not be restored — restoring it republishes the false sentences.check-empty-changeset.mjsreaches the same reading on its own and prints it in the job log unprompted.skip-changesetCheck ChangesetREDThe note
.changeset/18605-enable-on-install-one-authority.md—"@objectstack/spec": minor, pending, added by commit596090efbe(#19130) at 2026-09-20 10:43 UTC.changeset versiondeletes the fragment and publishes its text verbatim intopackages/spec/CHANGELOG.md.The window is measured, not hypothetical.
chore: version packages(PR #17076) is open right now and its file list carriesremoved .changeset/18605-enable-on-install-one-authority.md. Whichever of the two lands first decides whether the false sentences ship.What changed under it — old and new, verbatim
The two the card named
(1) old — the kernel copy's read behaviour:
(1) new:
The remainder of that sentence — "and the HTTP door does not forward the key down that seam — it calls
installPackage({ manifest, settings })and performs the enable/disable flip itself, because the durable half must follow the row that door returned rather than the request's intent" — is still true atorigin/mainand is left byte-for-byte as written.(2) old:
(2) new:
Two more, found by the re-derivation the claim demanded —⚠️ not in the card
These are the same class as (1) and (2): a statement about the published surface that the published surface no longer supports, in the same fragment, in the same release window, mechanically correctable to a form already pinned in the tree, on a file no other open PR modifies. They are called out separately so the confirmation above covers four corrections knowingly rather than two plus two silent ones. ⛔ If the seat prefers the card's exact two, (3) and (4) are a one-commit revert — say so and they come out.
(3) old — the install door's rule:
(3) new:
⭐ This one is the most consequential of the four, because it publishes a rule the maintainer re-ruled against.
?? truesays an absent key means enable; the live contract is 「缺省 = 保持,有旗 = 设置」 (maintainer ruling batch #157 item 5 letter C). The tree already records that this exact spelling is retired, in as many words —packages/objectql/src/protocol-install-package-enable-on-install.test.tsheader: «The card that filed this work describes the target as 「enableOnInstall ?? trueon install AND on re-install」. That sentence was written before #19291 landed and it is SPENT:?? trueon re-install is precisely what the HTTP door stopped doing.» Publishing it into a CHANGELOG would hand an upgrading reader the reading the repo removed from its own declarations.(4) old — a verbatim quotation of the authority's published description:
(4) new:
The claim ("its published description now says so") is true; the quotation is not — that tail no longer exists in the published string. A verbatim quotation of a mutable published description is exactly the shape that falls out of date, so the replacement names the mechanism instead of quoting the string.
Why these four are defects in the record and not dated readings
Every instrument below was read on
origin/mainat16d090ede0, at 2026-09-22T20:12Z–20:26Z. The card's own citations were treated as input and re-derived at source, ⛔ never quoted.16d090ede0packages/metadata-protocol/src/protocol.ts:22785const requestedEnabled = request.enableOnInstall;— the layer reads it.:22786–:22792if (requestedEnabled === true)⇒registry.enablePackage(manifest.id);else if (requestedEnabled === false)⇒registry.disablePackage(manifest.id); noelse⇒ an absent key makes no lifecycle call. Never truthiness, never??.packages/spec/src/kernel/package-registry.zod.ts:357trueenables,falsedisables, and ABSENT keeps the row's current lifecycle state…" — the description states the opposite of the fragment's report of it.packages/runtime/src/domains/packages.ts:1045,:1095–:1101,:1145protocolSvc.installPackage({ manifest, settings: body.settings })— noenableOnInstallin the call; then the door's own=== true/=== falsearms; thensetPackageDisabled(...)for the durable half. Still true ⇒ left as written.packages/spec/src/api/package-api.zod.ts:432andpackages/spec/src/kernel/package-registry.zod.ts:356z.boolean().optional(). Neither carries a default, so there is no default to be "the same". What is the same, and is what the parity pin holds, is the type, the optionality and the meaning.enableOnInstall ?? true"packages/runtime/src/domains/packages.ts:1095–:1101=== true/=== false, never a truthiness test and never a??default".git show 596090efbe:packages/runtime/src/domains/packages.ts,:819–:823git log --all -S "enableOnInstall ?? true"finds the string in no source file in the repo's history — only in prose. ⇒ (3) was false when written, not overtaken.packages/spec/src/api/package-api.zod.ts:433trueenables the installed row,falsedisables it, and ABSENT keeps the row's current lifecycle state (a fresh install lands enabled)". The quoted tail "the installed row'senabledis written from this key" is gone.When each became false — (1) and (2) were true when written and were overtaken within the week; (3) was false when written; (4) was overtaken. Either way the entry is release-notes input that has not shipped yet, so it is amended where it stands: AGENTS.md's release-artifact row rules that a factual error in a release-bound entry is amended in that entry, ⛔ never by an erratum in a later entry and ⛔ never by a rider on code changes.
596090efbe?482d584121(#19338, the primitive starts honouring it) and7e1b048a1d(#19691, the description is rewritten)z.boolean().default(true)fb59fb5e37(#19690, both becomeoptional())All four replacements are date-neutral: they name the mechanism (the three states and the verbs that apply them; the type/optionality/meaning the parity pin holds) rather than a count, an enumeration or a quoted string, so they stay true at
origin/mainand at publication alike. "Same type, same optionality, same meaning" is in particular the propertyapi/package-install-one-authority.test.tsmechanically holds — it parses both declarations over one matrix (absent,false,true, a string,null) and reds on any cell where they disagree — so the corrected sentence is kept true by a gate rather than by luck, which "same default" never could be.What deliberately did NOT change
Every other byte of the fragment stays as written, and these in particular were re-derived and deliberately left:
Past tense, describing the pre-[finding]
enableOnInstallis declared in three schemas and honoured by no handler — an author sets it and the runtime silently ignores it #18605 state, and true of it:Verified: both declarations really were
z.boolean().default(true)at596090efbe. A dated record's job is to say what was true when it was made, so overwriting it would falsify history rather than correct a record.A scope statement about what [finding]
enableOnInstallis declared in three schemas and honoured by no handler — an author sets it and the runtime silently ignores it #18605's own change did, not a claim about today's declarations:True of that change then, and still true of it now. The later removal of the defaults was a different change (spec:
PackageInstallRequestSchema.enableOnInstallmust stop erasing absence at parse time —.default(true)hides the case ruling batch #157 item 5 needs the install door to see #19273, fix(spec):enableOnInstallbecomesoptional()so absence survives the parse #19690) carrying its own notes.The whole parity-pin paragraph — re-derived and it stands:
api/package-install-one-authority.test.tsexists and pins the five-cell matrix named there, and theOS_EAGER_SCHEMAS=1cycle it describes is restated verbatim inkernel/package-registry.zod.ts's own doc block.The whole marketplace paragraph — re-derived and it stands:
MarketplaceInstallRequestSchema's subject fields arelistingId(marketplace.zod.ts:481),version,licenseKey(:487) andtenantId(:545), and its own description names itself "the marketplace channel's own install option, not the platform install-door key".The opening line's "declared in three published schemas" — re-derived:
grep -rn "enableOnInstall: z" packages/spec/src/returns exactly three declarations, and each names the authority in its own description.The
"@objectstack/spec": minorheader and theClause-②: yesline.Verification
Gate families derived from this worktree, ⛔ never from the shared checkout:
It derived 19 families at commit
fbb8952c3e, and confirmed the--repoassertion against this checkout'sorigin. All 19 were run, each exit code captured before any pipe, recorded ascommand :: exit code, and reconciled:18 of 19 exit 0. The one non-zero is the expected one:
node scripts/check-empty-changeset.mjs --base origin/main— exit 1, the route-0 red. Its output names this PR's class as DELIBERATE CORRECTION on its own and ends: "this gate stays red either way, and staying red is what puts the decision in front of a person instead of routing around it."Run in addition, because
dispatch-gatesflagged that this family's roster lives under.changeset, which is where this PR's only path is:node scripts/check-changeset-fixed.mjs— exit 0, ".changeset/config.json"fixed" group is in sync with 70 public workspace packages" (a verdict over a real population, not a vacuous green).Repo-wide
pnpm lintnarrowed to this diff, and the narrowing proven rather than asserted — all three readings, so the narrowing is a measurement and not a skip:ESLint({ cwd })instance:isPathIgnored('.changeset/18605-enable-on-install-one-authority.md')istrue, and the positive controlisPathIgnored('scripts/check-nul-bytes.mjs')isfalse— so the predicate is shown able to answer either way. Everyfilesglob ineslint.config.mjsnames TS/JS extensions only (**/*.{ts,tsx,mts,cts,js,jsx,mjs,cjs}and four narrower TS-only globs), and a case-insensitive count ofmarkdownor the markdown extension in that config is 0.--format jsonshape:lintFilesover both paths returns 2 entries; the changed path's entry iserrorCount 0, warningCount 1whose only message is "File ignored because no matching configuration was supplied" — zero rules evaluated — while the control path's entry is a genuinely lintederrorCount 0, warningCount 0with no ignore message.No package build, test or typecheck is owed: the diff touches one
.changeset/*.mdfile and no package source, so there is no affected-package closure to build and no package's public surface moves.dispatch-gatesindependently reports the change set as 1 path,+3 / -3, 6 changed lines.Control characters —
grep -naP '[\x00-\x08\x0b\x0c\x0e-\x1f\x7f]'over the changed file exits 1 (no hits), with the same pattern exiting 0 on a seeded BEL control file in the same run, and a near-miss class ([\x09]) exiting 1 on that same control file so the class is doing the discriminating.pnpm check:nul-bytesexits 0.Every zero above carries its controls. On the
grep -c -Finstrument over the changed file, atfbb8952c3e/ 2026-09-22T20:26Z: firing controlssame optionality= 1 andhonours the key on the registry row= 1 (the subject is alive on this instrument); measurementsenableOnInstall ?? true= 0,Same type, same default= 0,this layer does not read it= 0,is written from this key= 0; dark controlssame optionalities= 0 andenableOnInstall ?? false= 0.Acceptance notes
Observations found while verifying, deliberately not acted on and not filed:
"@objectstack/spec": patch; at source it isminor. Re-derived at16d090ede0: line 2 is"@objectstack/spec": minor. The header is not this PR's to change either way,check-changeset-no-majorexits 0 on it, and the discrepancy is an input-vs-source one rather than a defect in the tree. Recorded only so a re-measurer does not read it as drift.origin/main, substance identical. The card citesprotocol.ts:22773–22779; the arms are at:22785–:22792. It citespackage-api.zod.ts:434; the declaration is at:432.package-registry.zod.ts:356is exact. Noted only so a re-measurer does not read the drift as disagreement — this is precisely why the claim demanded re-derivation.?? truespelling appears nowhere else in the repo's release-bound prose.git grep -n "enableOnInstall ?? true"at16d090ede0returns exactly two carriers besides this fragment, both of which are about the spelling being retired rather than asserting it:packages/objectql/src/protocol-install-package-enable-on-install.test.ts:23and:188. No other.changeset/*.mdcarries it. Carrier: none needed.Generated by Claude Code